package com.zj.eswrapper.interfaces.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.zj.eswrapper.interfaces.IESearchWrapper;
import com.zj.eswrapper.model.Highlight;
import com.zj.eswrapper.model.Limit;

import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 分页以及排序等条件拼接器抽象类
 *
 * @author arthur_zhou
 * @date 2023/12/29 18:13
 */
public abstract class AbstractEsSearchWrapper<Field, SearchWrapper extends AbstractEsSearchWrapper<Field, SearchWrapper, SearchBuilder>, SearchBuilder>
        implements IESearchWrapper<Field, SearchWrapper, SearchBuilder> {

    /**
     * 当前类 this
     */
    protected final SearchWrapper child = (SearchWrapper) this;

    protected Limit limit;
    protected SearchBuilder builder;

    public AbstractEsSearchWrapper(SearchBuilder builder) {
        this.limit = new Limit();
        this.builder = builder;
    }

    public AbstractEsSearchWrapper(AbstractEsSearchWrapper<?, ?, SearchBuilder> searchWrapper) {
        limit = searchWrapper.limit;
        builder = searchWrapper.builder;
    }

    @Override
    public SearchWrapper select(Collection<String> fields) {
        if (CollectionUtil.isEmpty(fields)) {
            return child;
        }
        limit.getSelectList().addAll(fields);
        return child;
    }

    @Override
    public SearchWrapper noSelect(Collection<String> fields) {
        if (CollectionUtil.isEmpty(fields)) {
            return child;
        }
        limit.getNoSelectList().addAll(fields);
        return child;
    }

    @Override
    public SearchWrapper highlight(Integer fragmentSize, Integer numberOfFragments, Collection<String> fields) {
        if (CollectionUtil.isEmpty(fields)) {
            return child;
        }
        limit.getHighlightList().addAll(
                fields.stream()
                        .filter(StrUtil::isNotEmpty)
                        .map(field -> new Highlight(fragmentSize, numberOfFragments, field))
                        .collect(Collectors.toList())
        );
        return child;
    }

    @Override
    public SearchWrapper highlightPreTags(String... val) {
        if (Objects.isNull(val)) {
            return child;
        }
        limit.getHighlightPreTags().addAll(
                Stream.of(val).collect(Collectors.toList())
        );
        return child;
    }

    @Override
    public SearchWrapper highlightPostTags(String... val) {
        if (Objects.isNull(val)) {
            return child;
        }
        limit.getHighlightPostTags().addAll(
                Stream.of(val).collect(Collectors.toList())
        );
        return child;
    }

    @SafeVarargs
    @Override
    public final SearchWrapper select(Field... field) {
        return IESearchWrapper.super.select(field);
    }

    @SafeVarargs
    @Override
    public final SearchWrapper noSelect(Field... field) {
        return IESearchWrapper.super.noSelect(field);
    }

    @SafeVarargs
    @Override
    public final SearchWrapper orderByAsc(Field... field) {
        return IESearchWrapper.super.orderByAsc(field);
    }

    @SafeVarargs
    @Override
    public final SearchWrapper orderByDesc(Field... field) {
        return IESearchWrapper.super.orderByDesc(field);
    }

    @SafeVarargs
    @Override
    public final SearchWrapper orderByAsc(Object missing, Field... field) {
        return IESearchWrapper.super.orderByAsc(missing, field);
    }

    @SafeVarargs
    @Override
    public final SearchWrapper orderByDesc(Object missing, Field... field) {
        return IESearchWrapper.super.orderByDesc(missing, field);
    }

    @SafeVarargs
    @Override
    public final SearchWrapper highlight(Field... field) {
        return IESearchWrapper.super.highlight(field);
    }

    @SafeVarargs
    @Override
    public final SearchWrapper highlight(Integer fragmentSize, Integer numberOfFragments, Field... field) {
        return IESearchWrapper.super.highlight(fragmentSize, numberOfFragments, field);
    }

    @Override
    public SearchWrapper customSearch(Consumer<SearchBuilder> consumer) {
        if (Objects.isNull(consumer)) {
            return child;
        }
        consumer.accept(builder);
        return child;
    }
}
